﻿using System;
using System.Collections.Generic;

namespace MMonitor.PM6750
{
    public class ReceivedCodeTransV2:PM6750Package
    {
        readonly ReceivedDataModelV2 _rDataModel = new ReceivedDataModelV2();

        //指令格式：0x55 0xaa STATUS0 STATUS1 DATA ECGW3 ECGW2 ECGW1 ECGW0 SATW RESPW SUM
        public byte[] PackageData
        {
            get { return Package; }
            set { Package = value; }
        }
        public byte CPackageLength
        {
            get { return PackageLength; }
            set { PackageLength = value; }
        }

        public ReceivedCodeTransV2()
        {
            //包头{0x55,0xAA} + STATUS0 STATUS1 DATA ECGW3 ECGW2 ECGW1 ECGW0 SATW RESPW SUM  共12位
            PackageData = new byte[] {0x55, 0xAA, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5};
            CPackageLength = 0x0A;
        }

        void RefreshData()
        {
            PackageData = new byte[] { 0x55, 0xAA, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5 };
            CPackageLength = 0x0A;
        }
        /// <summary>
        /// 将数据包解析为实际数据
        /// </summary>
        /// <param name="inBytes"></param>
        /// <returns></returns>
        public ReceivedDataModelV2 TransReceivedData(byte[] inBytes)
        {
            RefreshData();
            if (CheckReceivedDataFormate(inBytes))
            {
                PackageData = inBytes;
                MainTransMethod(inBytes);
            }
            return _rDataModel;
        }
        /// <summary>
        /// 重写总解析函数
        /// </summary>
        /// <param name="inBts">byte类型数组</param>
        public void MainTransMethod(byte[] inBts)
        {
            /*校验数据是否完整/如果校验值不符合则跳出解析*/
            if (!CheckReceivedDataFormate(inBts)) return;
            try
            {
                // 解析STATUS0-按键状态
                TransKeyState(inBts[2]);
                //DataModel.KeysState = TransKeyState(inBts[2]);
                //解析STATUS1-心跳和脉搏声指示及DATA的数据内容
                List<byte> status1 = ChangeHexToBinList(inBts[3]);
                //DataModel.ECGHeartSound = status1[7] == 1;
                //DataModel.PulseSound = status1[6] == 1;
                //解析DATA内容,inBit[4]
                var switchStr = status1[3]*8 + status1[2]*4 + status1[1]*2 + status1[0];
                byte data = inBts[4];
                switch (switchStr)
                {
                    case 0: //心电状态（ECGS）
                        TransECGS(data);
                        break;
                    case 1: //脉搏氧状态（SATS）
                        TranSATS(data);
                        break;
                    case 2: //无创血压状态（NIBPS）
                        TransNIBPS(data);
                        break;
                    case 3: //心率（0~254）
                        _rDataModel.ECGParamsData1.HeartRate = data;
                        break;
                    case 4: //脉搏氧脉率（0~254）
                        _rDataModel.SPO2Data1.PulseRate = data;
                        break;
                    case 5: //无创血压脉率（0~254）
                        _rDataModel.NIBPData1.PulseRate = data;
                        break;
                    case 6: //ST（以二进制补码表示；-80~+80 表示–0.8mV~+0.8mV）
                        var tempST = Convert.ToString(data, 2);
                        _rDataModel.ECGParamsData1.STPotential = Convert.ToDecimal(tempST);
                        break;
                    case 7: //脉搏氧饱和度（0~100）
                        //DataModel.PulseOxygenPercentage = data;
                        break;
                    case 8: //袖带压力（0~250mmHg）
                        _rDataModel.NIBPData1.CuffPressure = data;
                        break;
                    case 9: //收缩压（0~250mmHg）
                        _rDataModel.NIBPData1.SystolicPressure = data;
                        break;
                    case 10: //舒张压（0~250mmHg
                        _rDataModel.NIBPData1.DiastolicPressure = data;
                        break;
                    case 11: //平均压（0~250mmHg）
                        _rDataModel.NIBPData1.AveragePressure = data;
                        break;
                    case 12: //呼吸率（0~99）
                        _rDataModel.ECGParamsData1.BreathRate = data;
                        break;
                    case 13: //体温1（（DATA+200）/10）
                        _rDataModel.TemperatureData1.TemperateValue1 = (200 + Convert.ToDecimal(data))/10;
                        break;
                    case 14: //呼吸增益(0,1,2,3)
                        //_rDataModel. = data;
                        break;
                    case 15: //体温2（（DATA+200）/10）
                        _rDataModel.TemperatureData1.TemperateValue2 = (200 + Convert.ToDecimal(data))/10;
                        break;
                }
                //解析最近四个采样点心电波形值
                byte[] ecgvalues = {inBts[5], inBts[6], inBts[7], inBts[8]};
                TransEcgWaveDate(ecgvalues);
                // 解析SATW,脉搏氧容积波形（0~99为有效数据）
                _rDataModel.SATWaveData = inBts[9];
                //解析RESPW-inBit[10]呼吸波形（0~63有效）
                _rDataModel.RESPWaveData = inBts[10];
            }
            catch (Exception)
            {
                return;
            }
        }

        /// <summary>
        /// 解析NIBPS数据
        /// </summary>
        /// <param name="inBt">数据字节</param>
        /// <returns></returns>
        private void TransNIBPS(byte inBt)
        {
            List<byte> transList = ChangeHexToBinList(inBt);
            
            _rDataModel.NIBPData1.NIBPTestState = transList[0] == 1 ? "正在测量" : "测量结束";
            _rDataModel.NIBPData1.NIBPTestMode = Enum.GetName(typeof(DataModel.EnumNIBPTestMode), (transList[2] * 2 + transList[1]));
            
            _rDataModel.NIBPData1.NIBPTestType = Enum.GetName(typeof(DataModel.EnumNIBPTestType),(transList[4]*2 + transList[3]*1));
        }

        /// <summary>
        /// 字节内容解析功能
        /// </summary>
        /// <param name="inBt">数据</param>
        /// <returns></returns>
        private void TranSATS(byte inBt)
        {
            List<byte> transList = ChangeHexToBinList(inBt);
            //血氧脉搏强度值
            var SQ = (transList[3]*8 + transList[2]*4 + transList[1]*2 + transList[0]); //拼合为二进制后转10进制
            if (SQ>8)
            {
                _rDataModel.SPO2Data1.SignalQuality = "数据无效";
            }
            else if (SQ < 3)
            {
                _rDataModel.SPO2Data1.SignalQuality = "信号弱";
            }
            else
            {
                _rDataModel.SPO2Data1.SignalQuality = "信号强度正常";
            }
            //搜索脉搏超时
            if(transList[4] == 1)_rDataModel.SPO2Data1.SPO2State = Enum.GetName(typeof(DataModel.EnumSPO2State),4);
            //未接传感器或手指
            if(transList[7] == 1)_rDataModel.SPO2Data1.SPO2State = Enum.GetName(typeof(DataModel.EnumSPO2State),2);
        }

        /// <summary>
        /// 字节数据解析功能
        /// </summary>
        /// <param name="inBt">字节数据</param>
        /// <returns></returns>
        private void TransECGS(byte inBt)
        {
            List<byte> transList = ChangeHexToBinList(inBt);//转八位二进制数组
            _rDataModel.ECGParamsData1.ECGLeadState = Enum.GetName(typeof (DataModel.EnumECGLeadState), transList[7]);
            
            _rDataModel.ECGParamsData1.ECGCurrentLead = Enum.GetName(typeof(DataModel.EnumECGLeadChioced), (transList[2]*4+transList[1]*2+transList[0]));
            
            _rDataModel.ECGParamsData1.ECGGain = Enum.GetName(typeof(DataModel.EnumECGGain), (transList[4]*2+transList[3]));
            
            _rDataModel.ECGParamsData1.ECGFilteringMode = Enum.GetName(typeof(DataModel.EnumECGFilteringMode), (transList[6] * 2 + transList[5]));
        }

        /// <summary>
        /// 解析Ecg波形数据
        /// </summary>
        /// <param name="bts">波形值</param>
        /// <returns>心电波形值</returns>
        private void TransEcgWaveDate(byte[] bts)
        {
            var ecgWaveValue = new List<byte>(4) { 0, 0, 0, 0 };
            for (int i = 0; i < bts.Length && i < 4; i++)
            {
                ecgWaveValue[i] = bts[i];
            }
            _rDataModel.ECGWaveData1 = new ReceivedDataModelV2.ECGWaveData(ecgWaveValue[0],ecgWaveValue[1],ecgWaveValue[2],ecgWaveValue[3]);
        }

        /// <summary>
        /// 转义按键状态字节
        /// </summary>
        /// <param name="inBt">按键状态值</param>
        /// <returns></returns>
        private void TransKeyState(byte inBt)
        {
            //var tempKeyState = new DtKeysState();
            //转二进制数组
            List<byte> sTempCode = ChangeHexToBinList(inBt);
            _rDataModel.KeysState1 = new ReceivedDataModelV2.KeysStateData(sTempCode[0], sTempCode[1], sTempCode[2], sTempCode[3], sTempCode[4], sTempCode[5], sTempCode[6]);
        }
        /// <summary>
        /// 验证数据包是否正确
        /// </summary>
        bool CheckReceivedDataFormate(byte[] inBytes)
        {
            return (inBytes.Length == CPackageLength + 2) && (GetSumValue(inBytes) == inBytes[11]);
        }
        /// <summary>
        /// 计算校验位值
        /// </summary>
        static byte GetSumValue(byte[] inBytes)
        {
            byte sum = 0x00;
            for (int i = 2; i < inBytes.Length-1; i++)
            {
                sum += inBytes[i];
            }
            return Convert.ToByte(sum%256);
        }
        /// <summary>
        /// 将数值转为二进制数串-//按照从高位到低位生成数组。如:5->110->0000 0110
        /// </summary>
        /// <param name="b">要转换的数字</param>
        /// <returns></returns>
        private List<byte> ChangeHexToBinList(byte b)
        {
            string bit = Convert.ToString(b, 2);//转换为2进制
            var bitList = new List<byte> { 0, 0, 0, 0, 0, 0, 0, 0 };
            int bitLength = bit.Length;
            for (int i = 0; i < bitLength; i++)
            {
                bitList[i] = Convert.ToByte(bit[bitLength - i - 1].ToString());
            }
            return bitList;
        }
    }
}
